/*
 * Copyright 2009 IT Mill Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package org.grumpybitz.sunrise;

import com.vaadin.Application;
import com.vaadin.data.Item;
import com.vaadin.data.Property;
import com.vaadin.data.Property.ValueChangeEvent;
import com.vaadin.event.ItemClickEvent;
import com.vaadin.event.ItemClickEvent.ItemClickListener;
import com.vaadin.ui.Button;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.SplitPanel;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Window.Notification;

/**
 * The Application's "main" class
 */
@SuppressWarnings("serial")
public class MyVaadinApplication extends Application implements
		Button.ClickListener, Property.ValueChangeListener, ItemClickListener {
	private Window window;

	private Button newContact = new Button("Add contact");
	private Button search = new Button("Search");
	private Button share = new Button("Share");
	private Button help = new Button("Help");
	private HorizontalSplitPanel horizontalSplit = new HorizontalSplitPanel();
	private ListView listView = null;
	private HelpWindow helpWindow = null;

	private NavigationTree tree = new NavigationTree(this);

	private SharingOptions shareWindow;

	@Override
	public void init() {

		buildMainLayout();
	}

	private void buildMainLayout() {
		window = new Window("Address Book Demo application");
		setMainWindow(window);

		VerticalLayout layout = new VerticalLayout();
		layout.setSizeFull();

		layout.addComponent(createToolbar());
		layout.addComponent(horizontalSplit);

		/* Allocate all available extra space to the horizontal split panel */

		layout.setExpandRatio(horizontalSplit, 1);
		/*
		 * Set the initial split position so we can have a 200 pixel menu to the
		 * left
		 */

		horizontalSplit.setSplitPosition(200, SplitPanel.UNITS_PIXELS);

		horizontalSplit.setFirstComponent(tree);

		getMainWindow().setContent(layout);

		showListView();
	}

	private void showListView() {
		setMainComponent(getListView());
	}

	private Window getHelpWindow() {
		if (helpWindow == null) {
			helpWindow = new HelpWindow();
		}
		return helpWindow;
	}

	private Window getShareWindow() {
		if (shareWindow == null) {
			shareWindow = new SharingOptions();
		}
		return shareWindow;
	}

	private void setMainComponent(Component c) {
		horizontalSplit.setSecondComponent(c);
	}

	private PersonList personList = null;
	private FirstForm personForm = null;

	private ListView getListView() {
		if (listView == null) {
			personList = new PersonList(this);
			personForm = new FirstForm(this);
			listView = new ListView(personList, personForm);
		}
		return listView;
	}

	public HorizontalLayout createToolbar() {

		search.addListener((Button.ClickListener) this);

		newContact.addListener((Button.ClickListener) this);

		share.addListener(new Button.ClickListener() {

			public void buttonClick(ClickEvent event) {
				getMainWindow().addWindow(getShareWindow());
			}

		});

		help.addListener(new Button.ClickListener() {

			public void buttonClick(ClickEvent event) {
				getMainWindow().addWindow(getHelpWindow());
			}

		});

		HorizontalLayout lo = new HorizontalLayout();
		lo.addComponent(newContact);
		lo.addComponent(search);
		lo.addComponent(share);
		lo.addComponent(help);

		return lo;

	}

	private CustomerContainer dataSource = CustomerContainer
			.createWithTestData();

	public CustomerContainer getDataSource() {
		return dataSource;
	}

	private SearchView searchView = null;

	private SearchView getSearchView() {
		if (searchView == null) {
			searchView = new SearchView(this);
		}
		return searchView;
	}

	public void buttonClick(ClickEvent event) {
		final Button source = event.getButton();
		if (source == search) {
			showSearchView();
		} else if (source == newContact) {
			showNewContactView();
		}

	}

	private void showNewContactView() {
		addNewContact();

	}

	private void showSearchView() {
		setMainComponent(getSearchView());
	}

	public void valueChange(ValueChangeEvent event) {
		Property property = event.getProperty();
		if (property == personList) {
			Item item = personList.getItem(personList.getValue());
			if (item != personForm.getItemDataSource()) {
				personForm.setItemDataSource(item);
			}
		}

	}

	public void itemClick(ItemClickEvent event) {
		if (event.getSource() == tree) {
			Object itemId = event.getItemId();
			if (itemId != null) {
				if (NavigationTree.SHOW_ALL.equals(itemId)) {
					showNewContactView();
				} else if (NavigationTree.SEARCH.equals(itemId)) {
					showSearchView();
				} else if (itemId instanceof SearchFilter) {
					search((SearchFilter) itemId);
				}
			}
		}

	}

	private void addNewContact() {
		showListView();
		personForm.addContact();
	}

	public void search(SearchFilter searchFilter) {
		// clear previous filters
		getDataSource().removeAllContainerFilters();
		// filter contacts with given filter
		getDataSource().addContainerFilter(searchFilter.getPropertyId(),
				searchFilter.getTerm(), true, false);

		getMainWindow().showNotification(
		         "Searched for " + searchFilter.getPropertyId() + "=*"
		         + searchFilter.getTerm() + "*, found "
		         + getDataSource().size() + " item(s).",
		         Notification.TYPE_TRAY_NOTIFICATION);

		showListView();
	}

	public void saveSearch(SearchFilter searchFilter) {
		tree.addItem(searchFilter);
		tree.setParent(searchFilter, NavigationTree.SEARCH);
		// mark the saved search as a leaf (cannot have children)
		tree.setChildrenAllowed(searchFilter, false);
		// make sure "Search" is expanded
		tree.expandItem(NavigationTree.SEARCH);
		// select the saved search
		tree.setValue(searchFilter);
	}
}
